﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.IO;

using MediaPortal.TvServer.WebServices;

namespace WebServerHost
{
    public partial class Main : Form
    {
        int _httpPort;
        string _tvServerHost;
        int _thumbWidth;
        int _thumbHeight;
        string _clientPlayer;
        int _playerType;
        string _userName;
        string _password;
        List<EncoderConfig> _encoderConfigs;
        Cassini.Server _webServer;

        public Main()
        {
            InitializeComponent();
            LoadConfig();

            nudPort.Value = (Decimal)_httpPort;
            edHost.Text = _tvServerHost;
            nudWidth.Value = _thumbWidth;
            nudHeight.Value = _thumbHeight;
            edPlayer.Text = _clientPlayer;
            edUid.Text = _userName;
            edPwd.Text = _password;
            cbPlayerType.SelectedIndex = _playerType;
            foreach (EncoderConfig cfg in _encoderConfigs)
            {
                DataGridViewRow row = new DataGridViewRow();
                row.CreateCells(grid);
                row.Cells[0].Value = cfg.displayName;
                row.Cells[1].Value = cfg.useTranscoding;
                row.Cells[2].Value = cfg.fileName;
                row.Cells[3].Value = cfg.args;
                row.Cells[4].Value = cfg.inputMethod.ToString();
                row.Cells[5].Value = cfg.outputMethod.ToString();
                grid.Rows.Add(row);
            }
            grid.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);
        }

        #region Persistance
        private void LoadConfig()
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(Application.StartupPath + "\\config.xml");
            XmlNode gNode = doc.SelectSingleNode("/appconfig/config");
            _httpPort = Int32.Parse(gNode.Attributes["httpport"].Value);

            if (gNode.Attributes["tvserverhost"] != null)
                _tvServerHost = gNode.Attributes["tvserverhost"].Value;
            if (string.IsNullOrEmpty(_tvServerHost))
                _tvServerHost = Environment.MachineName;
            _thumbHeight = Int32.Parse(gNode.Attributes["thumbheight"].Value);
            _thumbWidth = Int32.Parse(gNode.Attributes["thumbwidth"].Value);
            _clientPlayer = gNode.Attributes["clientplayerpath"].Value;
            _playerType = Int32.Parse(gNode.Attributes["playertype"].Value);
            _userName = gNode.Attributes["username"].Value;
            _password = gNode.Attributes["password"].Value;
            XmlNodeList nodes = doc.SelectNodes("/appconfig/transcoders/transcoder");
            _encoderConfigs = new List<EncoderConfig>();
            foreach (XmlNode node in nodes)
            {
                EncoderConfig cfg = new EncoderConfig(node.Attributes["name"].Value, (node.Attributes["usetranscoding"].Value == "1"), node.Attributes["filename"].Value, node.Attributes["args"].Value, (TransportMethod)Int32.Parse(node.Attributes["inputmethod"].Value), (TransportMethod)Int32.Parse(node.Attributes["outputmethod"].Value));
                _encoderConfigs.Add(cfg);
            }
        }

        public void NewAttribute(XmlNode node, string name, string value)
        {
            XmlAttribute attr = node.OwnerDocument.CreateAttribute(name);
            attr.InnerText = value;
            node.Attributes.Append(attr);
        }
        public void NewAttribute(XmlNode node, string name, bool value)
        {
            XmlAttribute attr = node.OwnerDocument.CreateAttribute(name);
            if (value)
                attr.InnerText = "1";
            else
                attr.InnerText = "0";
            node.Attributes.Append(attr);
        }
        public void NewAttribute(XmlNode node, string name, int value)
        {
            XmlAttribute attr = node.OwnerDocument.CreateAttribute(name);
            attr.InnerText = value.ToString();
            node.Attributes.Append(attr);
        }

        private void SaveConfig()
        {
            XmlDocument doc = new XmlDocument();
            XmlNode root = doc.CreateElement("appconfig");
            XmlNode gNode = doc.CreateElement("config");
            NewAttribute(gNode, "httpport", _httpPort);
            NewAttribute(gNode, "tvserverhost", _tvServerHost);
            NewAttribute(gNode, "thumbwidth", _thumbWidth);
            NewAttribute(gNode, "thumbheight", _thumbHeight);
            NewAttribute(gNode, "clientplayerpath", _clientPlayer);
            NewAttribute(gNode, "playertype", _playerType);
            NewAttribute(gNode, "username", _userName);
            NewAttribute(gNode, "password", _password);
            XmlNode transcoders = doc.CreateElement("transcoders");
            foreach (EncoderConfig cfg in _encoderConfigs)
            {
                XmlNode node = doc.CreateElement("transcoder");
                NewAttribute(node, "name", cfg.displayName);
                NewAttribute(node, "usetranscoding", cfg.useTranscoding);
                NewAttribute(node, "filename", cfg.fileName);
                NewAttribute(node, "args", cfg.args);
                NewAttribute(node, "inputmethod", (int)cfg.inputMethod);
                NewAttribute(node, "outputmethod", (int)cfg.outputMethod);
                transcoders.AppendChild(node);
            }

            root.AppendChild(gNode);
            root.AppendChild(transcoders);
            doc.AppendChild(root);
            doc.Save(Application.StartupPath + "\\config.xml");
        }
        #endregion

        private TransportMethod GetTransportMethod(string s)
        {
            switch (s)
            {
                case "Filename":
                    return TransportMethod.Filename;
                case "NamedPipes":
                    return TransportMethod.NamedPipe;
                case "StandardIn":
                    return TransportMethod.StandardIn;
                case "StandardOut":
                    return TransportMethod.StandardOut;
            }
            return TransportMethod.NamedPipe;
        }
        private void BuildConfig()
        {
            _httpPort = (int)nudPort.Value;
            _tvServerHost = edHost.Text;
            _thumbWidth = (int)nudWidth.Value;
            _thumbHeight = (int)nudHeight.Value;
            _clientPlayer = edPlayer.Text;
            _playerType = cbPlayerType.SelectedIndex;
            _userName = edUid.Text;
            _password = edPwd.Text;
            _encoderConfigs.Clear();
            foreach (DataGridViewRow row in grid.Rows)
            {
                if (row.Cells[0].Value != null)
                    _encoderConfigs.Add(new EncoderConfig(row.Cells[0].Value.ToString(), (bool)row.Cells[1].Value, row.Cells[2].Value.ToString(), row.Cells[3].Value.ToString(), GetTransportMethod(row.Cells[4].Value.ToString()), GetTransportMethod(row.Cells[5].Value.ToString())));
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            BuildConfig();
            SaveConfig();
        }

        private void btnStopServer_Click(object sender, EventArgs e)
        {
            _webServer.Stop();
            _webServer = null;
            linkLabel1.Visible = false;
            linkLabel2.Visible = false;
            toolStripStatusLabel1.Text = "WebServer stopped.";
        }

        private void btnStartServer_Click(object sender, EventArgs e)
        {
            button1_Click(sender, e);
            toolStripStatusLabel1.Text = "Starting webserver... This might take several seconds...";
            Update();
            _webServer = new Cassini.Server((int)nudPort.Value, "/", Application.StartupPath + "\\htdocs");
            _webServer.Start();
            linkLabel1.Text = "http://" + Environment.MachineName + ":" + nudPort.Value.ToString();
            linkLabel1.Visible = true;
            linkLabel2.Text = "http://" + Environment.MachineName + ":" + nudPort.Value.ToString() + "/TvServiceWebServices.asmx";
            linkLabel2.Visible = true;
            toolStripStatusLabel1.Text = "WebServer started.";
        }

        private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process proc = new System.Diagnostics.Process();
            proc.StartInfo.FileName = linkLabel1.Text;
            proc.Start();
        }

        private void linkLabel2_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process proc = new System.Diagnostics.Process();
            proc.StartInfo.FileName = linkLabel2.Text;
            proc.Start();
        }
    }
}
